package me.xiaolei.float_window

import android.app.Application
import android.content.Context
import android.content.res.Resources
import android.graphics.PixelFormat
import android.os.Build
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.WindowManager
import android.widget.FrameLayout
import android.util.DisplayMetrics
import android.util.TypedValue
import androidx.annotation.FloatRange


/**
 * 创建FloatView的创建类，可以在activity里或者service里，或者在独立的进程里
 */
class FloatViewBuilder constructor(private val layoutId: Int, _context: Context)
{
    // 上下文
    private val context: Context = if (_context is Application)
    {
        _context
    } else
    {
        _context.applicationContext
    }

    // 更新的监听
    private var onUpdate: OnUpdateListener? = null

    // 显示的监听
    private var onShow: OnShowListener? = null

    // 隐藏的监听
    private var onHide: OnHideListener? = null

    // 销毁的监听
    private var onDestroy: OnDestroyListener? = null

    // 坐标位置更新的监听
    private var onPosUpdate: OnPositionUpdateListener? = null

    // size
    private val size = ViewSize(300, 300)

    // 权限适配
    private var permissionAdapter: PermissionAdapter? = null

    // 可拖动
    private var draggable: Boolean = true

    // 控件的位置
    private val position = ViewPosition(0, 0)

    // 窗口管理器
    private val windowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager

    // 屏幕的信息，包括宽高
    private val displayMetric = DisplayMetrics()

    // 透明度
    private var alpha = 1f

    init
    {
        val display = windowManager.defaultDisplay
        display.getRealMetrics(displayMetric)
    }

    /**
     * 设置更新事件
     */
    fun onUpdate(onUpdate: OnUpdateListener): FloatViewBuilder
    {
        this.onUpdate = onUpdate
        return this
    }

    /**
     * 显示的事件
     */
    fun onShow(onShow: OnShowListener): FloatViewBuilder
    {
        this.onShow = onShow
        return this
    }

    /**
     * 隐藏事件
     */
    fun onHide(onHide: OnHideListener): FloatViewBuilder
    {
        this.onHide = onHide
        return this
    }

    /**
     * 销毁的监听
     */
    fun onDestroy(onDestroy: OnDestroyListener): FloatViewBuilder
    {
        this.onDestroy = onDestroy
        return this
    }

    /**
     * 大小,单位是DP
     */
    fun size(width_dp: Int, height_dp: Int): FloatViewBuilder
    {
        this.size.width = width_dp.dipToPixel
        this.size.height = height_dp.dipToPixel
        return this
    }

    /**
     * 权限适配器
     */
    fun permissionAdapter(adapter: PermissionAdapter): FloatViewBuilder
    {
        this.permissionAdapter = adapter
        return this
    }

    /**
     * 设置可拖拽
     */
    fun draggable(draggable: Boolean): FloatViewBuilder
    {
        this.draggable = draggable
        return this
    }

    /**
     * 设置窗口透明度,
     * 1.0 表示不透明
     * 0.0 表示完全透明
     */
    fun alpha(@FloatRange(from = 0.0, to = 1.0) alpha: Float): FloatViewBuilder
    {
        this.alpha = alpha
        return this
    }

    /**
     * 设置初始位置,这个是以一个控件的位置为参考点的
     * @param direction 作用于控件的方向
     * @param by 作为参考的控件
     * @param offsetX_dp X轴的偏移
     * @param offsetY_dp Y轴的偏移
     */
    fun position(direction: Direction, by: View, offsetX_dp: Int, offsetY_dp: Int): FloatViewBuilder
    {
        val xy = intArrayOf(0, 0)
        by.getLocationOnScreen(xy)
        val viewX = xy[0]
        val viewY = xy[1]

        val viewWidth = by.measuredWidth
        val viewHeight = by.measuredHeight
        when (direction)
        {
            Direction.LEFT_INNER ->
            {
                this.position.x = viewX + offsetX_dp.dipToPixel
                this.position.y = viewY - ((size.height - viewHeight) / 2) + offsetY_dp.dipToPixel
            }
            Direction.LEFT_OUTER ->
            {
                this.position.x = (viewX - size.width) + offsetX_dp.dipToPixel
                this.position.y = viewY - ((size.height - viewHeight) / 2) + offsetY_dp.dipToPixel
            }
            Direction.TOP_INNER ->
            {
                this.position.x = viewX - (size.width - viewWidth) / 2 + offsetX_dp.dipToPixel
                this.position.y = viewY + offsetY_dp.dipToPixel
            }
            Direction.TOP_OUTER ->
            {
                this.position.x = viewX - (size.width - viewWidth) / 2 + offsetX_dp.dipToPixel
                this.position.y = viewY - size.height + offsetY_dp.dipToPixel
            }
            Direction.RIGHT_INNER ->
            {
                this.position.x = viewX + viewWidth - size.width + offsetX_dp.dipToPixel
                this.position.y = viewY - ((size.height - viewHeight) / 2) + offsetY_dp.dipToPixel
            }
            Direction.RIGHT_OUTER ->
            {
                this.position.x = viewX + viewWidth + offsetX_dp.dipToPixel
                this.position.y = viewY - ((size.height - viewHeight) / 2) + offsetY_dp.dipToPixel
            }
            Direction.BOTTOM_INNER ->
            {
                this.position.x = viewX - (size.width - viewWidth) / 2 + offsetX_dp.dipToPixel
                this.position.y = viewY + viewHeight - size.height + offsetY_dp.dipToPixel
            }
            Direction.BOTTOM_OUTER ->
            {
                this.position.x = viewX - (size.width - viewWidth) / 2 + offsetX_dp.dipToPixel
                this.position.y = viewY + viewHeight + offsetY_dp.dipToPixel
            }
        }
        return this
    }

    /**
     * 设置初始位置
     */
    fun position(direction: Direction, by: View): FloatViewBuilder
    {
        return this.position(direction = direction, by = by, offsetX_dp = 0, offsetY_dp = 0)
    }

    /**
     * 设置初始位置,这里设置的是中心点位置
     * @param x_dp X 单位是DP
     * @param y_dp Y
     */
    fun position(x_dp: Int, y_dp: Int): FloatViewBuilder
    {
        return this.position(x_dp = x_dp, y_dp = y_dp, center = false)
    }

    /**
     * 设置初始位置,这里设置的是中心点位置
     * @param x_dp X 单位是DP
     * @param y_dp Y
     * @param center 是不是设置的中心点
     */
    fun position(x_dp: Int, y_dp: Int, center: Boolean): FloatViewBuilder
    {
        this.position.x = x_dp.dipToPixel - if (center) (this.size.width / 2) else 0
        this.position.y = y_dp.dipToPixel - if (center) (this.size.height / 2) else 0
        return this
    }

    /**
     * 坐标更新事件
     */
    fun onPositionUpdate(listener: OnPositionUpdateListener): FloatViewBuilder
    {
        this.onPosUpdate = listener
        return this
    }

    fun build(): IFloatDelegate
    {
        val params = buildParams()
        val rootView = buildRootView(params)
        return FloatDelegateImpl(
            context,
            draggable,
            onUpdate,
            onShow,
            onHide,
            onDestroy,
            permissionAdapter,
            onPosUpdate,
            windowManager,
            params,
            ViewHolder(rootView)
        )
    }

    /**
     * 创建顶部控件
     */
    private fun buildRootView(params: WindowManager.LayoutParams): View
    {
        val rootView = FrameLayout(context)
        val inflater = LayoutInflater.from(context)
        val layoutView = inflater.inflate(layoutId, rootView, false)
        rootView.addView(layoutView)
        return rootView
    }

    /**
     * 创建参数
     */
    private fun buildParams(): WindowManager.LayoutParams
    {
        val params = WindowManager.LayoutParams()
        params.format = PixelFormat.TRANSPARENT
        params.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or
                WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
        params.windowAnimations = android.R.style.Animation_Dialog
        params.systemUiVisibility =
            View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
        params.type = when
        {
            Build.VERSION.SDK_INT == Build.VERSION_CODES.N ->
            {
                WindowManager.LayoutParams.TYPE_PHONE
            }
            Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ->
            {
                WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
            }
            else ->
            {
                WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY
            }
        }
        params.width = size.width
        params.height = size.height
        params.gravity = Gravity.TOP or Gravity.START
        params.x = position.x
        params.y = position.y
        params.alpha = alpha
        return params
    }

    /**
     * dp 转 像素
     */
    private inline val Int.dipToPixel: Int
        get() = TypedValue.applyDimension(
            TypedValue.COMPLEX_UNIT_DIP,
            this.toFloat(),
            Resources.getSystem().displayMetrics
        ).toInt()

    /**
     * 控件大小
     */
    private inner class ViewSize(var width: Int, var height: Int)

    /**
     * 控件位置
     */
    private inner class ViewPosition(var x: Int, var y: Int)
}